From a52b81e4ddba30bb2eed3b018b23ebb096511e6b Mon Sep 17 00:00:00 2001 From: tsteven4 <13596209+tsteven4@users.noreply.github.com> Date: Tue, 27 Dec 2022 06:34:03 -0700 Subject: [PATCH] move xml tag utilities to xml_tag.cc (#960) * move xml tag utilities to xml_tag.cc they are already declared in src/core/xmltag.h * move xml_tag.cc to src/core, where it's h file is. * move global xml_tag routines into class. * make xml_next non-static. * make xml_findnext non-static. * make xml_findfirst non-static * make xml_attribute non-static * eliminate some shadowing * rename XmlTag class. * retire fs_xml_alloc. * use QStringView with XmlTag. * back off QStringView for xml_attribute for Qt 5. --- CMakeLists.txt | 2 +- gpx.cc | 8 ++-- gpx.h | 4 +- html.cc | 22 +++++------ kml.cc | 14 +++---- xmltag.cc => src/core/xmltag.cc | 66 +++++++++++++++++++++++++++------ src/core/xmltag.h | 40 ++++++++++++-------- text.cc | 22 +++++------ util.cc | 53 ++------------------------ 9 files changed, 120 insertions(+), 111 deletions(-) rename xmltag.cc => src/core/xmltag.cc (58%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a2b6fd63..caecf0c76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,6 +189,7 @@ set(SUPPORT src/core/usasciicodec.cc src/core/vector3d.cc src/core/xmlstreamwriter.cc + src/core/xmltag.cc strptime.c units.cc util.cc @@ -196,7 +197,6 @@ set(SUPPORT vecs.cc waypt.cc xmlgeneric.cc - xmltag.cc ) if(${QT_VERSION_MAJOR} EQUAL "6") set(SUPPORT ${SUPPORT} src/core/codecdevice.cc) diff --git a/gpx.cc b/gpx.cc index 05e64e66d..f671f42b8 100644 --- a/gpx.cc +++ b/gpx.cc @@ -218,7 +218,7 @@ GpxFormat::start_something_else(QStringView el, const QXmlStreamAttributes& attr return; } - auto* new_tag = new xml_tag; + auto* new_tag = new XmlTag; new_tag->tagname = el.toString(); const QXmlStreamNamespaceDeclarations ns = reader->namespaceDeclarations(); @@ -262,7 +262,7 @@ GpxFormat::start_something_else(QStringView el, const QXmlStreamAttributes& attr cur_tag->sibling = new_tag; new_tag->parent = nullptr; } else { - fs_xml* new_fs_gpx = fs_xml_alloc(kFsGpx); + auto* new_fs_gpx = new fs_xml(kFsGpx); new_fs_gpx->tag = new_tag; fs_ptr->FsChainAdd(new_fs_gpx); new_tag->parent = nullptr; @@ -901,7 +901,7 @@ GpxFormat::gpx_cdata(QStringView s) } if (cur_tag->child) { - xml_tag* tmp_tag = cur_tag->child; + XmlTag* tmp_tag = cur_tag->child; while (tmp_tag->sibling) { tmp_tag = tmp_tag->sibling; } @@ -1138,7 +1138,7 @@ GpxFormat::write_attributes(const QXmlStreamAttributes& attributes) const } void -GpxFormat::fprint_xml_chain(xml_tag* tag, const Waypoint* wpt) const +GpxFormat::fprint_xml_chain(XmlTag* tag, const Waypoint* wpt) const { while (tag) { writer->writeStartElement(tag->tagname); diff --git a/gpx.h b/gpx.h index cc8baa75b..98f68b0e7 100644 --- a/gpx.h +++ b/gpx.h @@ -204,7 +204,7 @@ private: void gpx_end(QStringView unused); void gpx_cdata(QStringView s); void write_attributes(const QXmlStreamAttributes& attributes) const; - void fprint_xml_chain(xml_tag* tag, const Waypoint* wpt) const; + void fprint_xml_chain(XmlTag* tag, const Waypoint* wpt) const; void write_gpx_url(const UrlList& urls) const; void write_gpx_url(const Waypoint* waypointp) const; void write_gpx_url(const route_head* rh) const; @@ -225,7 +225,7 @@ private: void gpx_write_bounds(); QXmlStreamReader* reader{}; - xml_tag* cur_tag{}; + XmlTag* cur_tag{}; QString cdatastr; char* opt_logpoint = nullptr; char* opt_humminbirdext = nullptr; diff --git a/html.cc b/html.cc index 19cebca01..17ea64553 100644 --- a/html.cc +++ b/html.cc @@ -147,25 +147,25 @@ HtmlFormat::html_disp(const Waypoint* wpt) const if (includelogs) { const auto* fs_gpx = reinterpret_cast(wpt->fs.FsChainFind(kFsGpx)); if (fs_gpx && fs_gpx->tag) { - xml_tag* root = fs_gpx->tag; - xml_tag* curlog = xml_findfirst(root, "groundspeak:log"); + XmlTag* root = fs_gpx->tag; + XmlTag* curlog = root->xml_findfirst(u"groundspeak:log"); while (curlog) { time_t logtime = 0; *file_out << "

\n"; - xml_tag* logpart = xml_findfirst(curlog, "groundspeak:type"); + XmlTag* logpart = curlog->xml_findfirst(u"groundspeak:type"); if (logpart) { *file_out << "" << logpart->cdata << " by "; } - logpart = xml_findfirst(curlog, "groundspeak:finder"); + logpart = curlog->xml_findfirst(u"groundspeak:finder"); if (logpart) { *file_out << "" << logpart->cdata.toHtmlEscaped() << " on "; } - logpart = xml_findfirst(curlog, "groundspeak:date"); + logpart = curlog->xml_findfirst(u"groundspeak:date"); if (logpart) { logtime = xml_parse_time(logpart->cdata).toTime_t(); struct tm* logtm = localtime(&logtime); @@ -177,17 +177,17 @@ HtmlFormat::html_disp(const Waypoint* wpt) const } } - logpart = xml_findfirst(curlog, "groundspeak:log_wpt"); + logpart = curlog->xml_findfirst(u"groundspeak:log_wpt"); if (logpart) { - double lat = xml_attribute(logpart->attributes, "lat").toDouble(); - double lon = xml_attribute(logpart->attributes, "lon").toDouble(); + double lat = logpart->xml_attribute("lat").toDouble(); + double lon = logpart->xml_attribute("lon").toDouble(); *file_out << "" << pretty_deg_format(lat, lon, degformat[2], " ", true) << "
\n"; } - logpart = xml_findfirst(curlog, "groundspeak:text"); + logpart = curlog->xml_findfirst(u"groundspeak:text"); if (logpart) { - QString encstr = xml_attribute(logpart->attributes, "encoded"); + QString encstr = logpart->xml_attribute("encoded"); bool encoded = !encstr.startsWith('F', Qt::CaseInsensitive); QString s; @@ -201,7 +201,7 @@ HtmlFormat::html_disp(const Waypoint* wpt) const } *file_out << "

\n"; - curlog = xml_findnext(root, curlog, "groundspeak:log"); + curlog = curlog->xml_findnext(root, u"groundspeak:log"); } } } diff --git a/kml.cc b/kml.cc index 9dbe69c4f..2e9263200 100644 --- a/kml.cc +++ b/kml.cc @@ -1213,22 +1213,22 @@ QString KmlFormat::kml_geocache_get_logs(const Waypoint* wpt) const return r; } - xml_tag* root = fs_gpx->tag; - xml_tag* curlog = xml_findfirst(root, "groundspeak:log"); + XmlTag* root = fs_gpx->tag; + XmlTag* curlog = root->xml_findfirst(u"groundspeak:log"); while (curlog) { // Unless we have a broken GPX input, these logparts // branches will always be taken. - xml_tag* logpart = xml_findfirst(curlog, "groundspeak:type"); + XmlTag* logpart = curlog->xml_findfirst(u"groundspeak:type"); if (logpart) { r = r + "

" + logpart->cdata + ""; } - logpart = xml_findfirst(curlog, "groundspeak:finder"); + logpart = curlog->xml_findfirst(u"groundspeak:finder"); if (logpart) { r = r + " by " + logpart->cdata; } - logpart = xml_findfirst(curlog, "groundspeak:date"); + logpart = curlog->xml_findfirst(u"groundspeak:date"); if (logpart) { gpsbabel::DateTime t = xml_parse_time(logpart->cdata); if (t.isValid()) { @@ -1236,14 +1236,14 @@ QString KmlFormat::kml_geocache_get_logs(const Waypoint* wpt) const } } - logpart = xml_findfirst(curlog, "groundspeak:text"); + logpart = curlog->xml_findfirst(u"groundspeak:text"); if (logpart) { r += "
"; r += logpart->cdata.toHtmlEscaped(); } r += "

"; - curlog = xml_findnext(root, curlog, "groundspeak:log"); + curlog = curlog->xml_findnext(root, u"groundspeak:log"); } return r; } diff --git a/xmltag.cc b/src/core/xmltag.cc similarity index 58% rename from xmltag.cc rename to src/core/xmltag.cc index d01594d56..2376bce3d 100644 --- a/xmltag.cc +++ b/src/core/xmltag.cc @@ -20,20 +20,70 @@ */ #include // for QString +#include // for QStringView +#include // for CaseInsensitive +#include // for QXmlStreamAttribute #include // for QXmlStreamAttributes -#include "defs.h" #include "src/core/xmltag.h" + +/* + * xml_tag utilities + */ + +XmlTag* XmlTag::xml_next(const XmlTag* root) +{ + XmlTag* cur = this; + if (cur->child) { + cur = cur->child; + } else if (cur->sibling) { + cur = cur->sibling; + } else { + cur = cur->parent; + if (cur == root) { + cur = nullptr; + } + if (cur) { + cur = cur->sibling; + } + } + return cur; +} + +XmlTag* XmlTag::xml_findnext(const XmlTag* root, QStringView name) +{ + XmlTag* result = this; + do { + result = result->xml_next(root); + } while (result && result->tagname.compare(name, Qt::CaseInsensitive)); + return result; +} + +XmlTag* XmlTag::xml_findfirst(QStringView name) +{ + return xml_findnext(this, name); +} + +QString XmlTag::xml_attribute(const QString& attrname) const +{ + for (const auto& attribute : this->attributes) { + if (attribute.qualifiedName().compare(attrname, Qt::CaseInsensitive) == 0) { + return attribute.value().toString(); + } + } + return QString(); +} + static void -free_xml_tag(xml_tag* tag) +free_xml_tag(XmlTag* tag) { while (tag) { if (tag->child) { free_xml_tag(tag->child); } - xml_tag* next = tag->sibling; + XmlTag* next = tag->sibling; delete tag; tag = next; } @@ -41,14 +91,14 @@ free_xml_tag(xml_tag* tag) // FIXME: at some point, this becomes a plain ole copy constructor. static void -copy_xml_tag(xml_tag** copy, xml_tag* src, xml_tag* parent) +copy_xml_tag(XmlTag** copy, XmlTag* src, XmlTag* parent) { if (!src) { *copy = nullptr; return; } - auto* res = new xml_tag; + auto* res = new XmlTag; *copy = res; res->tagname = (src->tagname); @@ -71,9 +121,3 @@ fs_xml* fs_xml::clone() const copy_xml_tag(&(copy->tag), tag, nullptr); return copy; } - -fs_xml* fs_xml_alloc(FsType type) -{ - auto* result = new fs_xml(type); - return result; -} diff --git a/src/core/xmltag.h b/src/core/xmltag.h index 6e276a161..4eb6fb963 100644 --- a/src/core/xmltag.h +++ b/src/core/xmltag.h @@ -19,26 +19,39 @@ #ifndef SRC_CORE_XMLTAG_H #define SRC_CORE_XMLTAG_H -#include // for QString -#include // for QXmlStreamAttributes +#include // for QString +#include // for QStringView +#include // for QXmlStreamAttributes -#include "defs.h" +#include "formspec.h" // for FormatSpecificData, FsType -class xml_tag + +class XmlTag { public: + + /* Member Functions */ + + XmlTag* xml_findnext(const XmlTag* root, QStringView name); + XmlTag* xml_findfirst(QStringView name); + QString xml_attribute(const QString& attrname) const; + + /* Data Members */ + QString tagname; QString cdata; QString parentcdata; QXmlStreamAttributes attributes; - xml_tag* parent{nullptr}; - xml_tag* sibling{nullptr}; - xml_tag* child{nullptr}; -}; + XmlTag* parent{nullptr}; + XmlTag* sibling{nullptr}; + XmlTag* child{nullptr}; -xml_tag* xml_findfirst(xml_tag* root, const QString& tagname); -xml_tag* xml_findnext(xml_tag* root, xml_tag* cur, const QString& tagname); -QString xml_attribute(const QXmlStreamAttributes& attributes, const QString& attrname); +private: + + /* Member Functions */ + + XmlTag* xml_next(const XmlTag* root); +}; struct fs_xml : FormatSpecificData { explicit fs_xml(FsType type) : FormatSpecificData(type) {} @@ -52,9 +65,6 @@ public: fs_xml* clone() const override; - xml_tag* tag{nullptr}; + XmlTag* tag{nullptr}; }; - -fs_xml* fs_xml_alloc(FsType type); - #endif // SRC_CORE_XMLTAG_H diff --git a/text.cc b/text.cc index 6b8363545..2dd985160 100644 --- a/text.cc +++ b/text.cc @@ -130,23 +130,23 @@ TextFormat::text_disp(const Waypoint* wpt) if (includelogs) { const auto* fs_gpx = reinterpret_cast(wpt->fs.FsChainFind(kFsGpx)); if (fs_gpx && fs_gpx->tag) { - xml_tag* root = fs_gpx->tag; - xml_tag* curlog = xml_findfirst(root, "groundspeak:log"); + XmlTag* root = fs_gpx->tag; + XmlTag* curlog = root->xml_findfirst(u"groundspeak:log"); while (curlog) { time_t logtime = 0; *file_out << "\n"; - xml_tag* logpart = xml_findfirst(curlog, "groundspeak:type"); + XmlTag* logpart = curlog->xml_findfirst(u"groundspeak:type"); if (logpart) { *file_out << logpart->cdata << " by "; } - logpart = xml_findfirst(curlog, "groundspeak:finder"); + logpart = curlog->xml_findfirst(u"groundspeak:finder"); if (logpart) { *file_out << logpart->cdata << " on "; } - logpart = xml_findfirst(curlog, "groundspeak:date"); + logpart = curlog->xml_findfirst(u"groundspeak:date"); if (logpart) { logtime = xml_parse_time(logpart->cdata).toTime_t(); struct tm* logtm = localtime(&logtime); @@ -158,16 +158,16 @@ TextFormat::text_disp(const Waypoint* wpt) } } - logpart = xml_findfirst(curlog, "groundspeak:log_wpt"); + logpart = curlog->xml_findfirst(u"groundspeak:log_wpt"); if (logpart) { - double lat = xml_attribute(logpart->attributes, "lat").toDouble(); - double lon = xml_attribute(logpart->attributes, "lon").toDouble(); + double lat = logpart->xml_attribute("lat").toDouble(); + double lon = logpart->xml_attribute("lon").toDouble(); *file_out << pretty_deg_format(lat, lon, degformat[2], " ", false) << "\n"; } - logpart = xml_findfirst(curlog, "groundspeak:text"); + logpart = curlog->xml_findfirst(u"groundspeak:text"); if (logpart) { - QString encstr = xml_attribute(logpart->attributes, "encoded"); + QString encstr = logpart->xml_attribute("encoded"); bool encoded = !encstr.startsWith('F', Qt::CaseInsensitive); QString s; @@ -181,7 +181,7 @@ TextFormat::text_disp(const Waypoint* wpt) } *file_out << "\n"; - curlog = xml_findnext(root, curlog, "groundspeak:log"); + curlog = curlog->xml_findnext(root, u"groundspeak:log"); } } } diff --git a/util.cc b/util.cc index b343a0dda..5b7ab0ce2 100644 --- a/util.cc +++ b/util.cc @@ -22,6 +22,7 @@ #include // for sort #include // for isspace, isalpha, ispunct, tolower, toupper #include // for errno +#include // for INT_MAX, INT_MIN #include // for fabs, floor #include // for va_list, va_end, va_start, va_copy #include // for size_t, vsnprintf, FILE, fopen, printf, sprintf, stderr, stdin, stdout @@ -32,6 +33,7 @@ #include // for QByteArray #include // for QChar, operator<=, operator>= +#include // for QDate #include // for QDateTime #include // for QFileInfo #include // for QList @@ -40,16 +42,15 @@ #include // for QTextBoundaryFinder, QTextBoundaryFinder::Grapheme #include // for QTextCodec #include // for operator<<, QTextStream, qSetFieldWidth, endl, QTextStream::AlignLeft -#include // for QXmlStreamAttribute -#include // for QXmlStreamAttributes #include // for CaseInsensitive +#include // for QTime #include // for QTimeZone #include // for qAsConst, qEnvironmentVariableIsSet, QAddConst<>::Type, qPrintable #include "defs.h" #include "src/core/datetime.h" // for DateTime #include "src/core/logging.h" // for Warning -#include "src/core/xmltag.h" // for xml_tag, xml_attribute, xml_findfirst, xml_findnext + #if Q_BYTE_ORDER == Q_BIG_ENDIAN # define i_am_little_endian 0 @@ -1344,52 +1345,6 @@ strip_html(const utf_string* in) #endif } -/* - * xml_tag utilities - */ - -xml_tag* xml_next(xml_tag* root, xml_tag* cur) -{ - if (cur->child) { - cur = cur->child; - } else if (cur->sibling) { - cur = cur->sibling; - } else { - cur = cur->parent; - if (cur == root) { - cur = nullptr; - } - if (cur) { - cur = cur->sibling; - } - } - return cur; -} - -xml_tag* xml_findnext(xml_tag* root, xml_tag* cur, const QString& tagname) -{ - xml_tag* result = cur; - do { - result = xml_next(root, result); - } while (result && result->tagname.compare(tagname, Qt::CaseInsensitive)); - return result; -} - -xml_tag* xml_findfirst(xml_tag* root, const QString& tagname) -{ - return xml_findnext(root, root, tagname); -} - -QString xml_attribute(const QXmlStreamAttributes& attributes, const QString& attrname) -{ - for (const auto& attribute : attributes) { - if (attribute.qualifiedName().compare(attrname, Qt::CaseInsensitive) == 0) { - return attribute.value().toString(); - } - } - return QString(); -} - QString get_filename(const QString& fname) { return QFileInfo(fname).fileName(); -- 2.30.2